package com.quanquan.user.service;

import DTO.PageDTO;
import DTO.user.UserDTO;
import com.quanquan.user.configBeans.RabbitSender;
import com.quanquan.user.dao.AbstractBatchDao;
import com.quanquan.user.entity.User;
import com.quanquan.user.entity.UserGroup;
import com.quanquan.user.entity.UserGroupRelationShip;
import com.quanquan.user.exception.UserGroupException;
import com.quanquan.user.repository.UserGroupRelationshipRepository;
import com.quanquan.user.repository.UserGroupRepository;
import com.quanquan.user.repository.UserRepository;
import com.quanquan.user.request.UserGroupRequestBody;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import utils.DateUtils;
import utils.StringUtil;
import utils.UUIDGenerator;

import javax.persistence.criteria.Predicate;
import javax.transaction.Transactional;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 功能描述:会员分组管理
 *
 * @ClassName: UserGroupService
 * @Author: xiaoqianh丶
 * @Date: 2019-03-19 15:10
 * @Version: V1.0
 */
@Service
@Transactional
public class UserGroupService extends AbstractBatchDao {
    private final UserGroupRepository userGroupRepository;

    private final UserGroupRelationshipRepository userGroupRelationshipRepository;
    private final RabbitSender rabbitSender;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    public UserGroupService(UserGroupRepository userGroupRepository, UserGroupRelationshipRepository userGroupRelationshipRepository, RabbitSender rabbitSender) {
        this.userGroupRepository = userGroupRepository;
        this.userGroupRelationshipRepository = userGroupRelationshipRepository;
        this.rabbitSender = rabbitSender;
    }

    public String createGroup(UserGroupRequestBody requestbody) {
        UserGroup userGroup = new UserGroup();
        userGroup.setId(UUIDGenerator.getUUID());
        userGroup.setCreateTime(DateUtils.currentDate());
        userGroup.setUpdateTime(DateUtils.currentDate());
        userGroup.setRemove(0);
        userGroup.setGroupName(requestbody.getGroupName());
        userGroup.setGroupInfo(requestbody.getGroupInfo());
        userGroupRepository.save(userGroup);
        return "创建分组成功";
    }

    /**
     * 根据Id查询用户分组
     *
     * @param id
     * @return
     */
    public UserGroup findById(String id) {
        return userGroupRepository.findById(id).orElse(null);
    }

    public List<UserGroup> findByName(String name) {
        return userGroupRepository.findAllByGroupNameAndRemove(name, 0);
    }

    /**
     * @param requestBody 查询所有分组
     * @return
     * @throws UserGroupException
     */
    public PageDTO<UserGroup> findAllGroup(UserGroupRequestBody requestBody) throws UserGroupException {
        String sortStr = StringUtil.isNotEmpty(requestBody.getSort()) ? requestBody.getSort() : "createTime";
        Sort sort = new Sort(Sort.Direction.DESC, sortStr);
        boolean asc = requestBody.isAsc();
        String keyword = requestBody.getKeyword();
        String fromDate = requestBody.getFromDate();
        String toDate = requestBody.getToDate();
        Pageable pageable = PageRequest.of(requestBody.getPage(), requestBody.getSize(), sort);
        Page<UserGroup> paged = userGroupRepository.findAll((Specification<UserGroup>) (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            // 创建具体查询条件
            if (!StringUtils.isEmpty(toDate)) {
                Date to = DateUtils.getEndOfDay(DateUtils.strToDate(toDate, DateUtils.DATE));
                predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get("createTime").as(Date.class), to));
            }
            if (StringUtils.isNotEmpty(fromDate)) {
                Date from = DateUtils.getStartOfDay(DateUtils.strToDate(fromDate, DateUtils.DATE));
                predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createTime").as(Date.class), from));
            }
            if (StringUtils.isNotEmpty(keyword)) {
                Predicate p1 = criteriaBuilder.like(root.get("groupName").as(String.class), "%" + keyword + "%");
                Predicate p2 = criteriaBuilder.or(criteriaBuilder.like(root.get("groupInfo").as(String.class), "%" + keyword + "%"), p1);
                predicates.add(p2);
            }
            predicates.add(criteriaBuilder.equal(root.get("remove"), 0));
            return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
        }, pageable);
        PageDTO<UserGroup> dto = new PageDTO<>();
        dto.setTotal(paged.getTotalElements());
        dto.setAsc(asc);
        dto.setKeyword(requestBody.getKeyword());
        dto.setToDate(toDate);
        dto.setFromDate(fromDate);
        dto.setList(paged.getContent());
        dto.setPage(requestBody.getPage());
        dto.setPageSize(requestBody.getSize());
        dto.setTotalPage(paged.getTotalPages());
        return dto;
    }


    /**
     * 分组添加会员成功
     *
     * @param groupId
     * @param userIds
     * @return
     */
    public String createGroupRelationShip(String groupId, List<String> userIds) {
        List<UserGroupRelationShip> list = new LinkedList<>();

        //根据分组id去重复
        List<UserGroupRelationShip> groupMemberInfo = userGroupRelationshipRepository.findByGroupIdAndRemove(groupId, 0);
        if (groupMemberInfo.size() > 0) {
            userGroupRelationshipRepository.removeAllRelationshipId(groupId);
        }

        for (String userId : userIds) {
            UserGroupRelationShip userGroupRelationShip = new UserGroupRelationShip();
            userGroupRelationShip.setId(UUIDGenerator.getUUID());
            userGroupRelationShip.setGroupId(groupId);
            userGroupRelationShip.setUserId(userId);
            userGroupRelationShip.setCreateTime(DateUtils.currentDate());
            userGroupRelationShip.setUpdateTime(DateUtils.currentDate());
            userGroupRelationShip.setRemove(0);
            list.add(userGroupRelationShip);
        }
        batchInsert(list);
        UserGroup userGroup = userGroupRepository.findUserGroupByIdAndRemove(groupId, 0);
        userGroup.setUpdateTime(DateUtils.currentDate());
        userGroupRepository.saveAndFlush(userGroup);
        return "分组添加会员成功";
    }


    /**
     * 根据分组id查询所有会员
     *
     * @param requestBody
     * @return
     */
    public List<String> findAllmemberByGroupId(UserGroupRequestBody requestBody) {
        String groupId = requestBody.getGroupId();
        List<UserGroupRelationShip> groupMemberInfo = userGroupRelationshipRepository.findByGroupIdAndRemove(groupId, 0);
        //获取分组下的所有用户id

        return groupMemberInfo.stream().map(UserGroupRelationShip::getUserId).collect(Collectors.toList());

    }

    /**
     * 删除分组
     *
     * @param groupId
     */
    public String removeGroup(String groupId) {
        UserGroup userGroup = userGroupRepository.findByIdAndRemove(groupId, 0);
        if (userGroup != null) {
            userGroup.setRemove(1);
            userGroupRepository.save(userGroup);
            //将对应的分组关系软删除
            userGroupRelationshipRepository.removeAllRelationshipByGroupId(groupId);
            return "删除分组成功";
        }
        return "改分组已不存在";
    }

    /**
     * 分组成员推送优惠券
     *
     * @param requestBody
     */
    public String pushCoupomForGroupMember(UserGroupRequestBody requestBody) {
        String groupId = requestBody.getGroupId();
        List<String> couponIds = requestBody.getCouponIds();
        String couponNum = requestBody.getCouponNum();
        List<UserGroupRelationShip> groupMemberInfo = userGroupRelationshipRepository.findByGroupIdAndRemove(groupId, 0);
        List<String> userIds = groupMemberInfo.stream().map(UserGroupRelationShip::getUserId).collect(Collectors.toList());

        sendCoupomMQ(couponIds, couponNum, userIds);
        return "优惠券推送成功";


    }

    private void sendCoupomMQ(List<String> coupomIds, String coupomNum, List<String> userIds) {
        Map<String, Object> properties = new HashMap<>();
        properties.put("userIds", userIds);
        properties.put("coupomIds", coupomIds);
        properties.put("coupomNum", coupomNum);

        String exchange = "coupon.exchange";
        String routingKey = "coupon.sendCoupon";

        rabbitSender.sendMessageToMQ("用户发券", properties, exchange, routingKey);
    }


    public PageDTO<UserDTO> queryCondition(UserGroupRequestBody requestBody) {
        Integer page = null == requestBody.getPage() ? 0 : requestBody.getPage();
        Integer size = null == requestBody.getSize() ? 10 : requestBody.getSize();
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
        Pageable pageable = PageRequest.of(page, size, sort);
        Page<UserGroupRelationShip> paged = userGroupRelationshipRepository.findAll((Specification<UserGroupRelationShip>) (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            if(StringUtil.isNotEmpty(requestBody.getGroupId())) {
                predicates.add(criteriaBuilder.equal(root.get("groupId").as(String.class),requestBody.getGroupId()));
            }
            predicates.add(criteriaBuilder.equal(root.get("remove"), 0));
            return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
        }, pageable);
        List<UserGroupRelationShip> content = paged.getContent();
        List<UserDTO> objects = new ArrayList<>();
        for (UserGroupRelationShip userGroupRelationShip: content) {
            List<User> users = userRepository.findUserByIdAndRemove(userGroupRelationShip.getUserId(),0);
            if (users.size()<= 0){
                continue;
            }
            //通过映射关系来赋值 //TODO 断点看一下
            UserDTO userDTO = new UserDTO();
            BeanUtils.copyProperties(users.get(0), userDTO);
            System.out.println(userDTO);
            objects.add(userDTO);
        }
        PageDTO<UserDTO> dto = new PageDTO<>();
        dto.setTotal(paged.getTotalElements());
        dto.setKeyword(requestBody.getKeyword());
        dto.setList(objects);
        dto.setPage(page);
        dto.setPageSize(size);
        dto.setTotalPage(paged.getTotalPages());
        return dto;
    }
}
